package webserver;

import java.net.*;
import java.io.*;

/**
 * Diese Klasse bildet die Schnittstelle zwischen dem Handler und dem Server.
 * Daten zwischen der Klasse Server und der Klasse Handler werden ausgetauscht.
 * Zudem werden die Verbindungen verwaltet.
 * @author Daniel
 * @brief Klasse Connection
 */
public class Connection extends Thread {

    private Socket clientSocket;
    
    private InputStream requestIS;
    private OutputStream responseIS;

    private String requestStr;
    private String responseStr;

    private Logging log;

    private Handler handler;

    private boolean running;

    /**
     * Konstruktor der Klasse Connection.
     * Variablen werden zurückgesetzt ind Inititialisiert.
     * @param pClientSocket Übergabe des Objekts Clientsocket.
     */
    public Connection(Socket pClientSocket) {

        clientSocket = pClientSocket; //get server socket to communicate with server and clients

        // init vars
        requestStr = "";
        responseStr = "";

        requestIS = null;
        responseIS = null;

        log = Logging.getInstance();

        running = true;

        this.start();

    }

    /**
     * Prüft ob Input oder Output.
     * Im Falles eines Requests werden die Daten des vom Client gesendeten Requests gelesen, und weitergeleitet an der Handler.
     * Der Handler wertet diese aus...
     * Anschließend werden die Daten des Handlers an den Client gesendet. (Response)
     * Es wird geprüft ob die Verbindung aufrecht erhalten werden muss (Keep-Alive) oder nicht.
     * Die Verbindung wird im Anschluss (ohne Keep-Alive) geschlossen.
     */
    @Override
    public void run() {

        try {
            
            while(running) {

                requestIS = null;
                responseIS = null;

                requestIS = clientSocket.getInputStream();
                responseIS = clientSocket.getOutputStream();

                int bytesToRead = requestIS.available(); // get available bytes in InputStream from clientSocket

                if(bytesToRead == 0) {
                    // nothing to do :)
                }
                else {

                    byte[] barray = new byte[bytesToRead];

                    try {
                        sleep(100); // wait 100ms to let client send all data
                    } catch (InterruptedException ex) {
                        // oops...
                    }

                    requestIS.read(barray, 0, bytesToRead); // write bytes from InputStream to "barray"

                    requestStr = new String(barray);

                    handler = new Handler(requestStr); // pass request from client to class "Handler"
                    responseIS.write(handler.getResponse());

                    try {
                        sleep(25); // wait 25ms to let server send all data
                    } catch (InterruptedException ex) {
                        // oops...
                    }

                    if(!handler.getKeepAlive()) { // no keep alive
                        closeConnection();
                        break;
                    }

                    responseIS = null;
                    requestIS = null;
                    
                }

            }

        } catch (IOException e) {            
            //e.printStackTrace();
            System.out.println("[Error]: Error on Input/Output");
            log.log("(ERROR): Error on Input/Output");
        }
        
    }

    /**
     * Schließt die Verbindung zum Client und schreibt in das Logfile.
     */
    public void closeConnection() {
        
        try {
            log.log("(INFO) Close connection with "+clientSocket);
            responseIS.close();
            requestIS.close();
            clientSocket.close();
        }
        catch(IOException ex) {            
            log.log("(ERROR): Could not close socket!");
        }

    }
    
}
